#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <time.h>
#include <string.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netdb.h>

#define GATE_PORT "36600"
#define MAX_PENDING_CONNECTIONS SOMAXCONN
#define BUFLEN 512


FILE *fp = NULL;  //the log file
int seg_cnt = 0;
char seg[BUFLEN]="\0";
int g_ret;
int loginfo(char *pstr)
{
	time_t lt;
	char *ptm ;
	char buf[BUFLEN];
	int i, cnt= 0;
	struct tm *p;
	lt = time(NULL);
	p = localtime(&lt);
	ptm = ctime(&lt);
	
	char hostname[BUFLEN]="\0";

	gethostname(hostname, BUFLEN);

	sprintf(buf, "[%s]%d-%d-%d %d:%d:%d %s\n", hostname, 1900+p->tm_year, 1 + p->tm_mon, p->tm_mday,  p->tm_hour, p->tm_min, p->tm_sec, pstr);
	
	for ( i = 0; buf[i] != '\0'; i++ ) 
	{
		cnt++;
	}
	fwrite(buf,cnt, 1, fp);	
	i = fflush(fp);
	return 0;
}
int get_para(char *p_para, int *p_min_cnt, int *p_max_cnt, int *p_time_interval)
{
	char min_cnt[8]="\0", max_cnt[8]= "\0", time_interval[8]= "\0";
	char list[3][8];
	char *p;
        char logbuffer[BUFLEN]="\0";
	int i = 0, j,k;
	p = p_para;
        sprintf(logbuffer, "I got para:%s",p);
        loginfo(logbuffer);
	for(j = 0; j < 3; j++)
	{
		for(k = 0; (*(p+i) != ',' && *(p+i) != '\0'); i++, k++)
		{
			min_cnt[k] = *(p+i);
		}
		i++;
		strcpy(list[j], min_cnt);
                sprintf(logbuffer, " list %d is %s", j, list[j]);
                loginfo(logbuffer);
		memset(min_cnt, 0, 8);
	}
	
	*p_min_cnt = atoi(list[0]);
	*p_max_cnt = atoi(list[1]);
	*p_time_interval = atoi(list[2]);
	return 0;
	
}

int gate()
{

	int listen_socket, work_socket, recv_len;
	int mail_socket, remote_addr_len;
	struct addrinfo hints, *res;
	struct sockaddr_storage remote_addr;
	char recvBuf[1024];
	char logbuf[BUFLEN];
	int ret, i,size;
	pid_t pid;
	int min_cnt, max_cnt, time_interval;
	char path[BUFLEN], para[BUFLEN], filename[BUFLEN];
	FILE* psegment;
	int open_ret, bytes_written;
	struct sockaddr_in clientAddr;
	
	memset(recvBuf, 0, sizeof(recvBuf));
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = AI_PASSIVE;
	
	getaddrinfo(NULL,GATE_PORT,&hints,&res);

	/* Initiate the listening socket */
	if ((listen_socket = socket(res->ai_family,
				    res->ai_socktype,
		       		    res->ai_protocol)) == -1)
	{
		   loginfo("Failed to create a listening socket.");
		   return 1;
	}

	/* Bind us to port GATE_PORT */
	if (bind(listen_socket,
		   res->ai_addr,
		   res->ai_addrlen) == -1)
	{
		   sprintf(logbuf, "Failed bind to %s.errno = %d",GATE_PORT, errno);
		   loginfo(logbuf);
		   return 1;
	}

	/* Set up listening */
	if (listen(listen_socket, MAX_PENDING_CONNECTIONS) == -1)
	{
		   loginfo("Failed to set up listening.");
		   return 1;
	}
	signal(SIGCHLD,SIG_IGN);  
	remote_addr_len = sizeof(clientAddr);
	sprintf(logbuf, "before accept");
	loginfo(logbuf);
	work_socket = accept( listen_socket,
                                      (struct sockaddr*)&clientAddr,
                                        &remote_addr_len);
	sprintf(logbuf,"accept is %d", work_socket);
	loginfo(logbuf);

	
	while (work_socket  != -1)
	{
		
		size = 0;
		char arg1[3]= "\0", arg2[3] = "\0", arg3[3] = "\0";
		FILE *fpgate;
		fpgate = fopen("/tmp/wzh000/gate_accept", "a+");
		fclose(fpgate);
		//sprintf(logbuf,"Received packet from %s:%d", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
		   //loginfo(logbuf);
		/* First recv parameters from segment. */
		ret = read(work_socket, para, 1024);
		sprintf(logbuf, "ret is %d,para are %s", ret, para);
		loginfo(logbuf);
		
		//get the min, max, interval from the string
		ret = get_para(para, &min_cnt, &max_cnt, &time_interval);
		if ( ret != 0)
		{
			sprintf(logbuf, "get_para failed. para is %s", para);
			loginfo(logbuf);
			close(work_socket);
			continue;

		}
		sprintf(logbuf, "parameters are %d, %d, %d", min_cnt, max_cnt, time_interval);
		loginfo(logbuf);
		sprintf(arg1, "%d", min_cnt);
		sprintf(arg2, "%d", max_cnt);
		sprintf(arg3, "%d", time_interval);
		/* Second save segment to a local file. */
		sprintf(filename, "wzh000_segment%d", seg_cnt);
		sprintf(seg, "/tmp/wzh000/wzh000_segment%d", seg_cnt);
		sprintf(logbuf, "path+filename is %s", seg);
		loginfo(logbuf);
		open_ret = open(seg, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
		if ( -1 == open_ret )
		{
			sprintf(logbuf, "open err : %d", errno);
			loginfo(logbuf);
			close(work_socket);
			continue;
		}
		while ((recv_len = read(work_socket, recvBuf, 1024)) > 0)
		{
			bytes_written =  write( open_ret, recvBuf, recv_len);
			size += bytes_written;
		//sprintf(logbuf, "bytes_written = %d", bytes_written);
		//loginfo(logbuf);
		}
		sprintf(logbuf, "received data: %6d bytes", size);
		loginfo(logbuf);
		close(open_ret);
		chmod(seg, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH);
		seg_cnt++;
		close(work_socket);

		
		//sprintf(logbuf, ".%s %s %s %s", seg, arg1, arg2, arg3);
                //system(logbuf);
		pid=fork();
		sprintf(logbuf, "pid = %d", pid);
		loginfo(logbuf);
		if ( 0 > pid)
		{
			loginfo("fork error segment");
			continue;
		}
		if ( 0 == pid )
		{
			sprintf(logbuf, "seg is %s, filename is %s", seg, filename);
			loginfo(logbuf);
		   	g_ret = execl(seg, filename, arg1, arg2, arg3, NULL);
		}
		sprintf(logbuf, "g_ret is %d", g_ret);
		loginfo(logbuf);	
		work_socket = accept( listen_socket, (struct sockaddr*)&clientAddr, &remote_addr_len);
	        sprintf(logbuf,"second accept is %d", work_socket);
       		loginfo(logbuf);

		   
	}
	sprintf(logbuf, "socket = %d, errno = %d", work_socket, errno);
	loginfo(logbuf);
	close(listen_socket);
	return 0;
}


int main(int argc, char **argv )
{
	/* Our process ID and Session ID */
        pid_t pid, sid;
	int ret;         
	if (access("/tmp/wzh000",0) == -1)
	{
		ret = mkdir("/tmp/wzh000", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
        	if( ret == -1)
        	{
			printf("mkdir err");
			exit (EXIT_FAILURE);
        	}
	}
        /* Fork off the parent process */
        pid = fork();
        if (pid < 0) {
		printf("fork failed! pid = %d\n", pid);
                exit(EXIT_FAILURE);
        }
        /* If we got a good PID, then
           we can exit the parent process. */
        if (pid > 0) {
                exit(EXIT_SUCCESS);
        }
	
        /* Create a new SID for the child process */
        sid = setsid();
        if (sid < 0) {
                /* Log the failure */
		printf("setsid failed. sid = %d\n", sid);
                exit(EXIT_FAILURE);
        }

	pid = fork();
	if (pid  > 0 )
	{ 
		exit (0); 
	}
	else if (pid < 0)
	{ 
		exit (1); 
	}

        /* Change the file mode mask */
        umask(0);
                
        /* Open any logs here */
	remove("/tmp/wzh000/gate.log");       
        fp = fopen( "/tmp/wzh000/gate.log", "a+");

	if ( NULL == fp)
	{
		printf("fopen err. errno=%d\n", errno);
		exit (EXIT_FAILURE);
	}       
        

        
        /* Change the current working directory */
        if ((chdir("/tmp/wzh000")) < 0) {
                /* Log the failure */
		printf("chdir failed\n");
                exit(EXIT_FAILURE);
        }
        
        /* Close out the standard file descriptors */
        close(STDIN_FILENO);
        close(STDOUT_FILENO);
        close(STDERR_FILENO);
        
        /* Daemon-specific initialization goes here */
        gate();
        /* The Big Loop */
	fclose(fp);
   	exit(EXIT_SUCCESS);
}

	
